package com.ruoyi.utils;

import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;


/**
 * 分布式同步锁工具类
 * @author Administrator
 *
 */
@Component
public class LockUtil {    
    @Autowired
    public RedisTemplate<String, String> redisTemplate;

    /**
     * 获取一个redis分布锁
     *
     * @param lockKey        锁住的key
     * @param lockExpireMils 锁住的时长。如果超时未解锁，视为加锁线程死亡，其他线程可夺取锁
     * @return
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean lock(String lockKey, long lockExpireMils) {
        Object returnValue = redisTemplate.execute((RedisCallback) connection -> {
            long nowTime = System.currentTimeMillis();
            Boolean acquire = connection.setNX(lockKey.getBytes(), String.valueOf(nowTime + lockExpireMils + 1).getBytes());
            if (acquire) {
                return Boolean.TRUE;
            } else {
                byte[] value = connection.get(lockKey.getBytes());
                if (Objects.nonNull(value) && value.length > 0) {
                    long oldTime = Long.parseLong(new String(value));
                    if (oldTime < nowTime) {
                        //connection.getSet：返回这个key的旧值并设置新值。
                        byte[] oldValue = connection.getSet(lockKey.getBytes(), String.valueOf(nowTime + lockExpireMils + 1).getBytes());
                        //当key不存时会返回空，表示key不存在或者已在管道中使用
                        return oldValue != null;
                    }
                }
            }
            return Boolean.FALSE;
        });
        if(returnValue==null){
        	return false;
        }
        return (Boolean)returnValue;
    }
    
    public void unLock(String lockKey){
    	redisTemplate.delete(lockKey);
    }
    
}
